package com.atstudent.gmall.product.service.impl;

import com.atstudent.gmall.common.constant.GmallConstant;
import com.atstudent.gmall.product.biz.SkuBizService;
import com.atstudent.gmall.product.service.BloomFilterService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;

/**
 * @Author 薛有朋
 * @CreatDate 2024/12/22 21:12
 **/
@Service
@Slf4j
public class BloomFilterServiceImpl implements BloomFilterService {

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private SkuBizService skuBizService;

    @Autowired
    private RedisTemplate<String , String> redisTemplate;

    @Override
    public void resetBloomFilter() {

        //1.创建新的布隆过滤器
        RBloomFilter<Long> rBloomFilter = redissonClient.getBloomFilter(GmallConstant.REDIS_SKUID_BLOOM_FILTER_NEW);
        //2.初始化新的布隆过滤器
        rBloomFilter.tryInit(1000000,0.000001);
        //3.执行业务代码-->把所有skuid存入布隆过滤器中
        List<Long> allSkuIds = skuBizService.findAllSkuIds();
        allSkuIds.forEach(skuId -> rBloomFilter.add(skuId));
        rBloomFilter.add(100L);
        log.info("新的分布式布隆过滤器已经初始化完毕...");

        //4.删除原有的布隆过滤器-->要保证前后的原子性 所以使用lua脚本
        String script = "redis.call('del' , KEYS[1])\n" +
                "redis.call('del' , \"{\"..KEYS[1]..\"}:config\")\n" +
                "redis.call('rename' , KEYS[2] , KEYS[1])\n" +
                "redis.call('rename' , \"{\"..KEYS[2]..\"}:config\" , \"{\"..KEYS[1]..\"}:config\")\n" +
                "return 1";

        //5.执行lua脚本
        Long result = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Arrays.asList(GmallConstant.REDIS_SKUID_BLOOM_FILTER, GmallConstant.REDIS_SKUID_BLOOM_FILTER_NEW));
        if (result == 1){
            log.info("分布式布隆过滤器重置成功了。。。");
        }

    }
}
